package cn.coufran.commons;

import cn.coufran.commons.exception.ServiceException;

import java.util.Objects;

/**
 * 标准结果
 * @author Coufran
 * @since 1.0.0
 * @version 1.0.0
 */
@SuppressWarnings("unused")
public class Result <T> {
    /** 响应码：成功 */
    public static final String CODE_OK = "200";
    /** 响应码：失败 */
    public static final String CODE_ERROR = "500";
    /** 响应消息：默认成功 */
    public static final String MSG_OK_DEFAULT = "成功";
    /** 响应消息：默认失败 */
    public static final String MSG_ERROR_DEFAULT = "失败";

    /** 是否成功 */
    private boolean success;
    /** 响应码 */
    private String code;
    /** 响应消息 */
    private String msg;
    /** 响应数据 */
    private T data;

    /**
     * 构造结果对象
     */
    public Result() {
    }

    /**
     * 构造结果对象
     * @param success 是否成功
     * @param code 响应码
     * @param msg 响应消息
     * @param data 响应数据
     */
    public Result(boolean success, int code, String msg, T data) {
        this.success = success;
        this.code = String.valueOf(code);
        this.msg = msg;
        this.data = data;
    }

    /**
     * 构造结果对象
     * @param success 是否成功
     * @param code 响应码
     * @param msg 响应消息
     * @param data 响应数据
     */
    public Result(boolean success, String code, String msg, T data) {
        this.success = success;
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    /**
     * 是否成功
     * @return 是否成功
     */
    public boolean isSuccess() {
        return success;
    }

    /**
     * 设置是否成功
     * @param success 是否成功
     */
    public void setSuccess(boolean success) {
        this.success = success;
    }

    /**
     * 获取响应码
     * @return 响应码
     */
    public String getCode() {
        return code;
    }

    /**
     * 设置响应码
     * @param code 响应码
     */
    public void setCode(int code) {
        this.code = String.valueOf(code);
    }

    /**
     * 设置响应码
     * @param code 响应码
     */
    public void setCode(String code) {
        this.code = code;
    }

    /**
     * 获取响应消息
     * @return 响应消息
     */
    public String getMsg() {
        return msg;
    }

    /**
     * 设置响应消息
     * @param msg 响应消息
     */
    public void setMsg(String msg) {
        this.msg = msg;
    }

    /**
     * 获取响应数据
     * @return 响应数据
     */
    public T getData() {
        return data;
    }

    /**
     * 设置响应数据
     * @param data 响应数据
     */
    public void setData(T data) {
        this.data = data;
    }

    /**
     * 设置响应码
     * @param code 响应码
     * @return 响应对象
     */
    public Result<T> code(int code) {
        this.code = String.valueOf(code);
        return this;
    }

    /**
     * 设置响应码
     * @param code 响应码
     * @return 响应对象
     */
    public Result<T> code(String code) {
        this.code = code;
        return this;
    }

    /**
     * 设置响应消息
     * @param msg 响应消息
     * @return 响应对象
     */
    public Result<T> msg(String msg) {
        this.msg = msg;
        return this;
    }

    /**
     * 设置响应数据
     * @param data 响应数据
     * @return 响应对象
     */
    public Result<T> data(T data) {
        this.data = data;
        return this;
    }

    /**
     * 成功
     * @param <T> 数据类型
     * @return 响应结果
     */
    public static <T> Result<T> ok() {
        return new Result<>(true, CODE_OK, MSG_OK_DEFAULT, null);
    }

    /**
     * 成功
     * @param code 响应码
     * @param <T> 数据类型
     * @return 响应结果
     */
    public static <T> Result<T> ok(int code) {
        return new Result<>(true, code, MSG_OK_DEFAULT, null);
    }

    /**
     * 成功
     * @param msg 响应消息
     * @param <T> 数据类型
     * @return 响应结果
     */
    public static <T> Result<T> ok(String msg) {
        return new Result<>(true, CODE_OK, msg, null);
    }

    /**
     * 成功
     * @param code 响应码
     * @param msg 响应消息
     * @param <T> 数据类型
     * @return 响应结果
     */
    public static <T> Result<T> ok(int code, String msg) {
        return new Result<>(true, code, msg, null);
    }

    /**
     * 成功
     * @param code 响应码
     * @param msg 响应消息
     * @param <T> 数据类型
     * @return 响应结果
     */
    public static <T> Result<T> ok(String code, String msg) {
        return new Result<>(true, code, msg, null);
    }

    /**
     * 成功
     * @param data 响应数据
     * @param <T> 数据类型
     * @return 响应结果
     */
    public static <T> Result<T> ok(T data) {
        return new Result<>(true, CODE_OK, MSG_OK_DEFAULT, data);
    }

    /**
     * 异常
     * @param <T> 数据类型
     * @return 响应结果
     */
    public static <T> Result<T> error() {
        return new Result<>(false, CODE_ERROR, MSG_ERROR_DEFAULT, null);
    }

    /**
     * 异常
     * @param code 响应码
     * @param <T> 数据类型
     * @return 响应结果
     */
    public static <T> Result<T> error(int code) {
        return new Result<>(false, code, MSG_ERROR_DEFAULT, null);
    }

    /**
     * 异常
     * @param msg 响应消息
     * @param <T> 数据类型
     * @return 响应结果
     */
    public static <T> Result<T> error(String msg) {
        return new Result<>(false, CODE_ERROR, msg, null);
    }

    /**
     * 异常
     * @param code 响应码
     * @param msg 响应消息
     * @param <T> 数据类型
     * @return 响应结果
     */
    public static <T> Result<T> error(int code, String msg) {
        return new Result<>(false, code, msg, null);
    }

    /**
     * 异常
     * @param code 响应码
     * @param msg 响应消息
     * @param <T> 数据类型
     * @return 响应结果
     */
    public static <T> Result<T> error(String code, String msg) {
        return new Result<>(false, code, msg, null);
    }

    /**
     * 校验结果
     * @return 响应结果
     * @throws ServiceException 校验失败
     */
    public Result<T> check() {
        if (!success) {
            throw new ServiceException(code, msg);
        }
        return this;
    }

    /**
     * 校验状态码
     * @param code 目标状态码
     * @return 响应结果
     * @throws ServiceException 校验失败
     */
    public Result<T> checkCode(int code) {
        return this.checkCode(String.valueOf(code));
    }

    /**
     * 校验状态码
     * @param code 目标状态码
     * @return 响应结果
     * @throws ServiceException 校验失败
     */
    public Result<T> checkCode(String code) {
        if (!Objects.equals(code, this.code)) {
            throw new ServiceException(code, msg);
        }
        return this;
    }

    /**
     * 转换为字符串
     * @return 字符串
     */
    @Override
    public String toString() {
        return "Result{" +
                "success=" + success +
                ", code='" + code + '\'' +
                ", msg='" + msg + '\'' +
                ", data=" + data +
                '}';
    }
}
